
function newElement(tagName,innerHTML,option){
    var el=document.createElement(tagName);
    if(typeof innerHTML =="object"){
        option=innerHTML;
    }else if(innerHTML!=null){
        el.innerHTML=innerHTML;
    }
    for(var key in option){
        el.setAttribute(key,option[key])
    }
    Object.defineProperties(el,{
        "addClass":{
            "value":function () {
                if (this.classList) {
                    for (var i = 0; i < arguments.length; i++) {
                        this.classList.add(arguments[i]);
                    }
                } else {
                    //兼容IE9+
                    for (var i = 0; i < arguments.length; i++) {
                        if (typeof arguments[i] == "string" && this.className.indexOf(arguments[i]) == -1) {
                            this.className = (this.className + " " + arguments[i]).trim();
                        }
                    }
                }
                return this;
            }
        },
        "removeClass":{
            "value":function () {
                if(this.classList){
                    for (var i = 0; i < arguments.length; i++) {
                        this.classList.remove(arguments[i]);
                    }
                }else {
                    //兼容IE9+
                    var cls=this.className.split(/\s+/);
                    for(let i=0;i<arguments.length;i++){
                        p=cls.indexOf(arguments[i]);
                        if(p>-1)  cls[p]="";
                    }
                    this.className=cls.join(" ").trim()
                }
                return this;
            }
        },
        "hasClass":{
            "value":function (cls) {
                if(!cls) return false;
                return this.className.indexOf(cls)>=0
            }
        },
        "append":{
            "value":function () {
                for(var i=0;i<arguments.length;i++){
                    if(arguments[i]){
                        this.appendChild(arguments[i])
                    }
                }
                return this;
            }
        }
    });
    return el;
};


(function(){
    var month=["一","二","三","四","五","六","七","八","九","十","十一","十二"];
    var week=["日","一","二","三","四","五","六"];
    //休息日用1标识
    var holiday=1;
    //工作日用0标识
    var workday=0;

    /** 初始化节日 */
    function initHoliday(h){
        if(!h) h={name:"",plans:[]};
        Object.defineProperties(h,{
            getPlan:{
                value:function (date) {
                    date=new Date(date).toLocaleDateString();
                    if(!date) return null;
                    if(Array.isArray(this.plans)){
                        for (var j = 0; j < this.plans.length; j++) {
                            if(date==new Date(this.plans[j].date).toLocaleDateString()){
                                return  this.plans[j];
                            }
                        }
                    }else {
                        this.plans=[];
                        return null;
                    }
                }
            },
            removePlan:{
                value:function(date){
                    var plan=this.getPlan(date);
                    if(!plan) return;
                    var i =this.plans.indexOf(plan);
                    for(;i>=0 && i<this.plans.length-1;i++){
                        this.plans[i]=this.plans[i+1];
                    }
                    this.plans.length=this.plans.length-1;
                }
            },
            putPlan:{
                value: function(date,type){
                    var plan=this.getPlan(date);
                    if(!plan && type!=null) {
                        this.plans.push({date:date,type:type});
                    }else if(plan){
                        if(type!=null){
                            plan.type=type;
                        }else{
                            this.removePlan(date);
                        }
                    }
                }
            }
        });
        
        return h;
    }

    /**
     * 
     * @param {string|Element} el 
     * @param {Date} date
     * @param {Array} holidays
     */
    function Lunar(el,date,holidays){
        this.editTmp=null;
        this.ctrl="add";
        this.date=date||new Date();
        
        this.__box=newElement("div",{class:"lunar-box"});
        this.__head=newElement("div",{class:"lunar-head"});
        this.__body=newElement("table",{class:"lunar-body"});
        
        if(typeof el=="string") {
            el=document.querySelector(el);
        }else if(el instanceof Element && el.tagName==="DIV"){
            //this.dom=el;
        }else{
            throw "元素选择错误:"+el;
        }
        if(el==null) throw "元素选择错误:"+el;

        el.appendChild(this.__box);
        this.__box.appendChild(this.__head);
        this.__box.appendChild(this.__body);
        this.setHolidays(holidays);
        this.renderHead();
        this.renderWeek();
        this.renderDays();
        
    }

    Lunar.prototype.setHolidays=function(holidays){
        this.holidays=(Array.isArray(holidays))?holidays:[];
        for (var i = 0; i < this.holidays.length; i++) {
            var holiday=this.holidays[i];
            initHoliday(holiday);
        }
        if(this.__holiday){
            this.renderHoliday();
            this.renderDays();
        }
    };

    Lunar.prototype.render=function(date){
        if(date)this.date=new Date(date);
        this.renderYear();
        this.renderMonth();
        this.renderDays();
    };
    /**保存事件 */
    Lunar.prototype.onSave=function(oldVal,newVal){
        this.success();
    };
    /**保存成功 */
    Lunar.prototype.success=function(){
        if(!this.__holiday.data){
            this.holidays.push(this.editTmp);
        }else{
            this.__holiday.data.name=this.editTmp.name;
            this.__holiday.data.plans=this.editTmp.plans;
        }
        
        this.__input.addClass("lunar-hide");
        this.__holiday.removeClass("lunar-hide");
        this.__ctrl.removeClass("save").addClass("edit");
        this.__ctrl.innerHTML="<i class='iconfont icon-edit'>"
        this.renderHoliday();
        this.__holiday.value=this.editTmp.name;
        this.__holiday.data=this.editTmp;
        this.editTmp=null;
        this.renderDays();
    };
    /**保存取消 */
    Lunar.prototype.cancel=function(){
        this.editTmp=null;
        this.__input.addClass("lunar-hide");
        this.__holiday.removeClass("lunar-hide");
        this.removeClass("save").addClass("edit");
        this.__ctrl.innerHTML="<i class='iconfont icon-edit'>"
        this.renderDays();
    };

    Lunar.prototype.renderHead=function(){
        var _this=this;
        this.__head.innerHTML="";
        this.renderYear();
        this.__lastMonth=newElement("button","<",{class:"lunar-btn",type:"button",title:"上个月"});
        this.__head.appendChild(this.__lastMonth);
        this.renderMonth();
        this.__nextMonth=newElement("button",">",{class:"lunar-btn",type:"button",title:"下个月"});
        this.__head.appendChild(this.__nextMonth);
        this.__head.appendChild(document.createTextNode(" "));
        this.__lastMonth.onclick=function(ev){
            _this.date.setMonth(_this.date.getMonth()-1)
            _this.render()
        }
        this.__nextMonth.onclick=function(ev){
            _this.date.setMonth(_this.date.getMonth()+1)
            _this.render()
        }

        this.renderHoliday();
        this.__ctrl=newElement("button","<i class='iconfont icon-add'>",{class:"lunar-btn add",type:"button",title:"新增假期"});
        this.__today=newElement("a","返回今天",{class:"lunar-btn ",href:"javascript:;"});
        this.__head.appendChild(this.__ctrl);
        this.__head.appendChild(document.createTextNode(" "));
        this.__head.appendChild(this.__today);
        this.__ctrl.onclick=function (ev) {
            if(this.hasClass("add") || this.hasClass("edit")){
                if(_this.__holiday.data){
                    _this.editTmp=JSON.parse(JSON.stringify(_this.__holiday.data))
                }else{
                    _this.editTmp={name:"",plan:[]};
                }
                initHoliday(_this.editTmp);
                _this.__input.removeClass("lunar-hide");
                _this.__holiday.addClass("lunar-hide");
                this.innerHTML="<i class='iconfont icon-save'>";
                this.removeClass("add").removeClass("edit").addClass("save");
                this.title="保存";
                _this.__input.value=_this.editTmp.name;
                _this.renderDays();
            }else if(this.hasClass("save")){
                try {
                    if(typeof _this.onSave ==="function"){
                        _this.onSave(_this.__holiday.data,_this.editTmp);
                    }
                } catch (e) {
                    console.log(e)
                }
            }
        };
        this.__today.onclick=function(){
            _this.render(new Date());
        }
    };
    /**
     * 年份选择
     */
    Lunar.prototype.renderYear=function(){
        var _this=this;
        if(!this.__year){
            this.__year=newElement("select",{class:"lunar-year"});
            this.__head.appendChild(this.__year);
            this.__head.appendChild(document.createTextNode(" "));
            this.__year.onchange=function (ev) {
                _this.date.setFullYear(parseInt(this.value));
                _this.renderYear();
                _this.renderDays();
            }
        }
        this.__year.innerText="";
        for(var i=this.date.getFullYear()-10;i<this.date.getFullYear()+10;i++){
            var opt=newElement("option",{value:i});
            opt.innerText=i+"年";
            opt.selected=i===this.date.getFullYear();
            this.__year.appendChild(opt)
        }
    };
    /**
     * 月份选择
     */
    Lunar.prototype.renderMonth=function(){
        var _this=this;
        if(!this.__month) {
            this.__month=newElement("select",{class:"lunar-month"});
            this.__head.appendChild(this.__month);
            this.__month.onchange=function (ev) {
                _this.date.setMonth(parseInt(this.value));
                _this.renderDays();
            }
        }
        this.__month.innerText="";
        for(var i=0;i<12;i++){
            var opt=newElement("option",{value:i});
            opt.innerText=month[i]+"月";
            opt.selected=i===this.date.getMonth();
            this.__month.appendChild(opt)
        }

    };
    /**
     * 节日下拉选择渲染
     */
    Lunar.prototype.renderHoliday=function(){
        var _this=this;
        /**获取节日最开始日期 */
        function minDay(plans) {
            var min=plans[0];
            for(var i=1;i<plans.length;i++){
                var day=plans[i];
                if(min.type===workday){
                    min=day;
                }else if(day.type===holiday && new Date(min.date).getTime()>new Date(day.date).getTime()){
                    min=day;
                }
            }
            return min;
        }
        if(!this.__holiday){
            this.__holiday=newElement("select",{class:"lunar-holiday"});
            this.__head.appendChild(this.__holiday);
            this.__holiday.onchange=function (ev) {
                if(this.value){
                    this.data=this.selectedOptions[0].data;
                    var min=minDay(this.data.plans);
                    _this.date=new Date(min.date);
                    _this.renderMonth();
                    _this.renderDays();
                    _this.__ctrl.innerHTML="<i class='iconfont icon-edit'></i>";
                    _this.__ctrl.title="编辑";
                    _this.__ctrl.removeClass("add").addClass("edit");
                }else {
                    this.data=undefined;
                    _this.__ctrl.innerHTML="<i class='iconfont icon-add'></i>";
                    _this.__ctrl.title="新增假期";
                    _this.__ctrl.removeClass("add").addClass("edit");
                }
            };
            this.__input=newElement("input",{class:"lunar-holiday lunar-hide",placeholder:"输入假期名称"});
            this.__head.appendChild(this.__input);
            this.__input.onchange=function () {
                _this.editTmp.name=this.value;
            }
        }
        this.__holiday.innerHTML="";
        this.__holiday.appendChild(newElement("option","节假日安排",{value:""}))
        for(var i=0;i<this.holidays.length;i++){
            var opt=newElement("option",{value:this.holidays[i].name});
            opt.data=this.holidays[i];
            opt.innerText=this.holidays[i].name;
            this.__holiday.appendChild(opt)
        }

    };

    Lunar.prototype.renderWeek=function(){
        var thead=this.__body.querySelector("thead");
        if(!thead) thead=this.__body.createTHead();
        thead.innerHTML="";
        var tr=newElement("tr",{class:"lunar-week"});
        thead.appendChild(tr);
        var th=null;
        for(var i=1;i<7;i++){
            th=newElement("th",week[i]);
            tr.appendChild(th);
        }
        th.addClass("lunar-weekend");
        tr.appendChild(newElement("th","日",{week:0,class:"lunar-weekend"}));
    };
    /**
     * 判断当前时间是否是假期安排
     * @param date
     * @returns {*}
     */
    Lunar.prototype.isHoliday=function(date){
        for(var i=0;i<this.holidays.length;i++){
            var holiday=this.holidays[i];
            day=holiday.getPlan(date);
            if(day){
                return {holiday:holiday,day:day};
            }
        }
    };
    /**
     * 假期渲染
     * @param el
     * @param date
     */
    Lunar.prototype.renderSign=function (el,date){
        var _this=this;
        var sign=newElement("div",{class:"lunar-sign",date:date});
        var h=newElement("span","休",{class:"lunar-holiday"});
        var w=newElement("span","班",{class:"lunar-workday"});
        var data=this.isHoliday(date);
        function click() {
            if(this.hasClass("active")){
                this.removeClass("active");
                _this.editTmp.removePlan(this.plan.date);
            }else {
                this.opposed.removeClass("active");
                this.addClass("active")
                _this.editTmp.putPlan(this.plan.date,this.plan.type);
            }
        }
        if(this.editTmp && (!data || data.holiday==this.__holiday.data)){
            var tem=this.editTmp.getPlan(date);
            sign.appendChild(h);
            sign.appendChild(w);
            h.plan={date:date,type:holiday};
            h.opposed=w;
            h.onclick=click;
            w.opposed=h;
            w.plan={date:date,type:workday};
            w.onclick=click;
            if(tem && tem.type==workday){
                w.addClass("active");
            }else if(tem && tem.type==holiday){
                h.addClass("active");
            }    
        }else if(data && data.day.type==workday){
            sign.appendChild(w);
            el.addClass("lunar-workday");
            el.title=data.holiday.name;
        }else if(data && data.day.type==holiday){
            sign.appendChild(h);
            el.addClass("lunar-holiday");
            el.title=data.holiday.name;
        }

        el.appendChild(sign);
        //el.addClass("lunar-sign")
        
    };

    Lunar.prototype.renderDays=function(){
        var tbody=this.__body.querySelector("tbody");
        if(tbody==null) tbody=this.__body.createTBody();
        tbody.innerHTML="";
        var date=new Date(this.date);
        date.setDate(1);
        if(date.getDay()==0){
            date.setDate(date.getDate()-6)
        }else{
            date.setDate(date.getDate()+(1-date.getDay()))
        }
        do{
            var tr=newElement("tr");
            for(var i=0;i<7;i++){
                var td=newElement("td");
                var div=newElement("div","<span>"+date.getDate()+"</span>",{class:"lunar-day"});
                if(date.getDay()==0 || date.getDay()==6){
                    div.addClass("lunar-weekend");
                }
                if(date.getMonth()<this.date.getMonth()){
                    div.addClass("last-month");
                }else if(date.getMonth()>this.date.getMonth()){
                    div.addClass("next-month");
                }
                var n=new Date();
                if(date.toLocaleDateString()==n.toLocaleDateString()){
                    div.addClass("lunar-today");
                }
                
                td.appendChild(div);
                tr.appendChild(td);
                this.renderSign(td,date.toLocaleDateString())
                date.setDate(date.getDate()+1)
            }
            tbody.appendChild(tr);
        }while(date.getMonth()<=this.date.getMonth())
    };



    window.Lunar=Lunar;
})();

